﻿using Sys.Workflow.Bpmn.Models;
using Sys.Workflow.Engine.Impl.Persistence.Entity;
using Sys.Workflow.Engine.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sys.Workflow.Engine.dynamic
{
    /* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


    public class MoveExecutionEntityContainer
    {

        protected List<IExecutionEntity> executions;
        protected List<string> moveToActivityIds;
        protected bool moveToParentProcess;
        protected bool moveToSubProcessInstance;
        protected bool directExecutionMigration;
        protected string callActivityId;
        protected long callActivitySubProcessVersion;
        protected CallActivity callActivity;
        protected string subProcessDefKey;
        protected IProcessDefinition subProcessDefinition;
        protected BpmnModel subProcessModel;
        protected BpmnModel processModel;
        protected IExecutionEntity superExecution;
        protected bool isMultiInstanceExecutionWithChildExecutions;
        protected string newAssigneeId;
        protected string newOwnerId;
        protected Dictionary<string, IExecutionEntity> continueParentExecutionMap = new Dictionary<string, IExecutionEntity>();
        protected Dictionary<string, FlowElementMoveEntry> moveToFlowElementMap = new Dictionary<string, FlowElementMoveEntry>();
        protected Dictionary<string, FlowElementMoveEntry> currentActivityToNewElementMap = new Dictionary<string, FlowElementMoveEntry>();
        protected Dictionary<string, Dictionary<string, object>> flowElementLocalVariableMap = new Dictionary<string, Dictionary<string, object>>();
        protected List<string> newExecutionIds = new List<string>();
        protected Dictionary<string, IExecutionEntity> createdEventSubProcesses = new Dictionary<string, IExecutionEntity>();

        public MoveExecutionEntityContainer(List<IExecutionEntity> executions, List<string> moveToActivityIds)
        {
            this.executions = executions;
            this.moveToActivityIds = moveToActivityIds;
        }

        public List<IExecutionEntity> GetExecutions()
        {
            return executions;
        }

        public List<string> GetMoveToActivityIds()
        {
            return moveToActivityIds;
        }

        public bool IsMoveToParentProcess()
        {
            return moveToParentProcess;
        }

        public void SetMoveToParentProcess(bool moveToParentProcess)
        {
            this.moveToParentProcess = moveToParentProcess;
        }

        public bool IsMoveToSubProcessInstance()
        {
            return moveToSubProcessInstance;
        }

        public void SetMoveToSubProcessInstance(bool moveToSubProcessInstance)
        {
            this.moveToSubProcessInstance = moveToSubProcessInstance;
        }

        public bool IsDirectExecutionMigration()
        {
            return directExecutionMigration;
        }

        public void SetDirectExecutionMigration(bool directMigrateUserTask)
        {
            this.directExecutionMigration = directMigrateUserTask;
        }

        public string GetCallActivityId()
        {
            return callActivityId;
        }

        public void SetCallActivityId(string callActivityId)
        {
            this.callActivityId = callActivityId;
        }

        public long GetCallActivitySubProcessVersion()
        {
            return callActivitySubProcessVersion;
        }

        public void SetCallActivitySubProcessVersion(long callActivitySubProcessVersion)
        {
            this.callActivitySubProcessVersion = callActivitySubProcessVersion;
        }

        public CallActivity GetCallActivity()
        {
            return callActivity;
        }

        public void SetCallActivity(CallActivity callActivity)
        {
            this.callActivity = callActivity;
        }

        public string GetSubProcessDefKey()
        {
            return subProcessDefKey;
        }

        public void SetSubProcessDefKey(string subProcessDefKey)
        {
            this.subProcessDefKey = subProcessDefKey;
        }

        public IProcessDefinition GetSubProcessDefinition()
        {
            return subProcessDefinition;
        }

        public void SetSubProcessDefinition(IProcessDefinition subProcessDefinition)
        {
            this.subProcessDefinition = subProcessDefinition;
        }

        public BpmnModel GetProcessModel()
        {
            return processModel;
        }

        public void SetProcessModel(BpmnModel processModel)
        {
            this.processModel = processModel;
        }

        public BpmnModel GetSubProcessModel()
        {
            return subProcessModel;
        }

        public void SetSubProcessModel(BpmnModel subProcessModel)
        {
            this.subProcessModel = subProcessModel;
        }

        public IExecutionEntity GetSuperExecution()
        {
            return superExecution;
        }

        public bool IsMultiInstanceExecutionWithChildExecutions()
        {
            return isMultiInstanceExecutionWithChildExecutions;
        }

        public void SetMultiInstanceExecutionWithChildExecutions(bool isMultiInstanceExecutionWithChildExecutions)
        {
            this.isMultiInstanceExecutionWithChildExecutions = isMultiInstanceExecutionWithChildExecutions;
        }

        public void SetNewAssigneeId(string newAssigneeId)
        {
            this.newAssigneeId = newAssigneeId;
        }

        public string GetNewAssigneeId()
        {
            return newAssigneeId;
        }

        public string GetNewOwnerId()
        {
            return newOwnerId;
        }

        public void SetNewOwnerId(string newOwnerId)
        {
            this.newOwnerId = newOwnerId;
        }

        public void SetSuperExecution(IExecutionEntity superExecution)
        {
            this.superExecution = superExecution;
        }

        public void AddContinueParentExecution(string executionId, IExecutionEntity continueParentExecution)
        {
            continueParentExecutionMap.Add(executionId, continueParentExecution);
        }

        public IExecutionEntity GetContinueParentExecution(string executionId)
        {
            return continueParentExecutionMap[executionId];
        }

        public void AddMoveToFlowElement(string activityId, FlowElementMoveEntry flowElementMoveEntry)
        {
            moveToFlowElementMap.Add(activityId, flowElementMoveEntry);
        }

        public void AddMoveToFlowElement(string activityId, FlowElement originalFlowElement, FlowElement newFlowElement)
        {
            moveToFlowElementMap.Add(activityId, new FlowElementMoveEntry(originalFlowElement, newFlowElement));
        }

        public void AddMoveToFlowElement(string activityId, FlowElement originalFlowElement)
        {
            moveToFlowElementMap.Add(activityId, new FlowElementMoveEntry(originalFlowElement, originalFlowElement));
        }

        public FlowElementMoveEntry GetMoveToFlowElement(string activityId)
        {
            return moveToFlowElementMap[activityId];
        }

        public List<FlowElementMoveEntry> GetMoveToFlowElements()
        {
            return new List<FlowElementMoveEntry>(moveToFlowElementMap.Values);
        }

        public void AddCurrentActivityToNewElement(string curentActivityId, FlowElement originalFlowElement, FlowElement newFlowElement)
        {
            currentActivityToNewElementMap.Add(curentActivityId, new FlowElementMoveEntry(originalFlowElement, newFlowElement));
        }

        public FlowElementMoveEntry GetCurrentActivityToNewElement(string curentActivityId)
        {
            return currentActivityToNewElementMap[curentActivityId];
        }

        public List<string> GetNewExecutionIds()
        {
            return newExecutionIds;
        }

        public bool HasNewExecutionId(string executionId)
        {
            return newExecutionIds.Contains(executionId);
        }

        public void SetNewExecutionIds(List<string> newExecutionIds)
        {
            this.newExecutionIds = newExecutionIds;
        }

        public void AddNewExecutionId(string executionId)
        {
            this.newExecutionIds.Add(executionId);
        }

        public IExecutionEntity GetCreatedEventSubProcess(string processDefinitionId)
        {
            return createdEventSubProcesses[processDefinitionId];
        }

        public void AddCreatedEventSubProcess(string processDefinitionId, IExecutionEntity executionEntity)
        {
            createdEventSubProcesses.Add(processDefinitionId, executionEntity);
        }

        public Dictionary<string, Dictionary<string, object>> GetFlowElementLocalVariableMap()
        {
            return flowElementLocalVariableMap;
        }

        public void SetFlowElementLocalVariableMap(Dictionary<string, Dictionary<string, object>> flowElementLocalVariableMap)
        {
            this.flowElementLocalVariableMap = flowElementLocalVariableMap;
        }

        public void AddLocalVariableMap(string activityId, Dictionary<string, object> localVariables)
        {
            this.flowElementLocalVariableMap.Add(activityId, localVariables);
        }

        public class FlowElementMoveEntry
        {

            protected FlowElement originalFlowElement;
            protected FlowElement newFlowElement;

            public FlowElementMoveEntry(FlowElement originalFlowElement, FlowElement newFlowElement)
            {
                this.originalFlowElement = originalFlowElement;
                this.newFlowElement = newFlowElement;
            }

            public FlowElement GetOriginalFlowElement()
            {
                return originalFlowElement;
            }

            public FlowElement GetNewFlowElement()
            {
                return newFlowElement;
            }
        }
    }
}
